﻿Imports Microsoft.VisualBasic.ApplicationServices
Class MainWindow
    Private _FxS As FxStream
    Private _Offset As Long
    Private _LastOffset As Long
    Private _FocusOffset As Long
    Private _SelectStartOffset As Long
    Private _SelectEndOffset As Long
    Private _Selected As Boolean
    Private _FileSize As Long
    Private _Lines As String()
    Private _SelectRanges As Generic.List(Of FxRange)
    Private _SelectRangeCount As Long
    Private _PrintableStr As String
    Private _SelectStartP As TextPointer
    Private _SelectEndP As TextPointer
    Private _SelectStrStartP As TextPointer
    Private _SelectStrEndP As TextPointer
    Private _RowHeight As Double
   


    Private Sub MainWindow_Loaded(ByVal sender As Object, ByVal e As System.Windows.RoutedEventArgs) Handles MainWindow.Loaded
        Try
            _PrintableStr = "!#$%&()*+,-./:;<=>?@[]\{}^_|~/0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
            Dim iFxFS As FxFormatStructures
            Dim iFxData As FxData
            Dim args(10) As String
            args = Environment.GetCommandLineArgs()
            Dim iXmlFile As String = "" 
            Dim iSourceFile As String = "" 
            If args.Length = 1 Then
                ShowMessage(" Syntax FFNavigator.exe <zipfile> or FFNavigator.exe <xmlfile> <zipfile>")
                Environment.Exit(0)
            End If
            If args.Length = 2 Then
                iSourceFile = args(1)
                Dim iExeDir As String
                iExeDir = args(0).Substring(0, args(0).LastIndexOf("\"))
                iXmlFile = iExeDir + "\" + "PkZip.xml"
               
            Else
                iXmlFile = args(1)
                iSourceFile = args(2)
            End If
            If Not FileIO.FileSystem.FileExists(iSourceFile) Then
                ShowMessage("File Not Found " + iSourceFile)
                Environment.Exit(0)
            End If
            If Not FileIO.FileSystem.FileExists(iXmlFile) Then
                ShowMessage("File Not Found " + iXmlFile)
                Environment.Exit(0)
            End If
            
            Dim iEncoding As New System.Text.ASCIIEncoding
            Me.Title = "FFNavigator " + iSourceFile

            iFxFS = FxXMLReader.ParseFxXML(iXmlFile)
            _FileSize = My.Computer.FileSystem.GetFileInfo(iSourceFile).Length
            iFxData = FxXMLReader.ParseFileData(iFxFS, iSourceFile, iXmlFile)
            Me.TVStructure.Items.Add(iFxData)
            _FxS = New FxStream(iSourceFile)
            _Offset = 0
            Dim iRows As Integer
            Dim iStrToPrint As New System.Text.StringBuilder
            Dim iBytes() As Byte
            Dim iCurrentOffset As Long
            Dim i, j As Integer

            If _FileSize Mod 16 = 0 Then
                iRows = _FileSize / 16
            Else
                iRows = (_FileSize - (_FileSize Mod 16)) / 16 + 1
            End If
            ReDim _Lines(iRows)
            Dim iOffsetLines(iRows) As String
            Dim iStrLines(iRows) As String
            For i = 0 To iRows - 1
                iStrToPrint = New System.Text.StringBuilder
                iCurrentOffset = _FxS.GetOffset()
                iBytes = _FxS.ReadBytes(16)
                iOffsetLines(i) = String.Format("{0,8:X8}  ", iCurrentOffset)
                If iBytes.Length = 16 Then
                    For j = 0 To 3
                        iStrToPrint.Append(String.Format("{0,2:X2}{1,2:X2}{2,2:X2}{3,2:X2}", iBytes(j * 4 + 0), iBytes(j * 4 + 1), iBytes(j * 4 + 2), iBytes(j * 4 + 3)))
                        iStrToPrint.Append(" ")
                    Next
                Else
                    Dim iCount As Integer
                    For j = 0 To iBytes.Length - 1
                        iStrToPrint.Append(String.Format("{0,2:X2}", iBytes(j)))
                        iCount = iCount + 1
                        If iCount = 4 Then
                            iStrToPrint.Append(" ")
                            iCount = 0
                        End If
                    Next
                End If
                iStrToPrint.Append(" ")
                iStrLines(i) = GetPrintableString(iBytes)
                _Lines(i) = iStrToPrint.ToString
            Next
            RTBOffset.AppendText(String.Join(vbCr, iOffsetLines))
            RTBHex.AppendText(String.Join(vbCr, _Lines))
            RTBStr.AppendText(String.Join(vbCr, iStrLines))
            _Selected = False
            _RowHeight = RTBHex.FontSize * 1.133
        Catch ex As Exception
            ShowMessage(" Critical Error " + ex.Message)
        End Try
    End Sub
    Private Sub ShowMessage(ByVal message As String)
        MessageBox.Show(message)
    End Sub
    Private Function GetPrintableString(ByRef aBytes As Byte()) As String
        Dim iStr As String = ""
        For Each iByte As Byte In aBytes
            Dim iOf As Integer = _PrintableStr.IndexOf(Chr(iByte))
            If iOf > 0 Then
                iStr = iStr + Chr(iByte)
            Else
                iStr = iStr + "."
            End If
        Next
        Return iStr
    End Function

    Private Sub TVStructure_SelectedItemChanged(ByVal sender As Object, ByVal e As System.Windows.RoutedPropertyChangedEventArgs(Of Object)) Handles TVStructure.SelectedItemChanged

        Dim iFxData As FxData
        Dim iOffset As Long
        Dim iEnd As Long
        Dim iRows As Integer
        iFxData = Me.TVStructure.SelectedItem
        If iFxData Is Nothing Then
            Return
        End If
        If iFxData.Size <= 0 Then
            If _Selected Then
                ClearSelection()
            End If
            _Selected = False
            Return
        End If
        Dim iTopRow As Double
        iRows = (iFxData.Offset - (iFxData.Offset Mod 16)) / 16
        iTopRow = iRows
        iOffset = iRows * 38 + CountDisplayLen(iFxData.Offset Mod 16)

        iEnd = iFxData.Offset + iFxData.Size
        iRows = (iEnd - (iEnd Mod 16)) / 16
        iEnd = iRows * 38 + CountDisplayLen((iFxData.Offset + iFxData.Size) Mod 16)

        SetHexSelection(iOffset + 2, iEnd + 2, iTopRow)

        iRows = (iFxData.Offset - (iFxData.Offset Mod 16)) / 16
        iOffset = iRows * 17 + ((iFxData.Offset) Mod 16)

        iEnd = iFxData.Offset + iFxData.Size
        iRows = (iEnd - (iEnd Mod 16)) / 16
        iEnd = iRows * 17 + ((iFxData.Offset + iFxData.Size) Mod 16)
        SetStrSelection(iOffset + 2, iEnd + 2, iTopRow)
        _Selected = True
    End Sub
    Private Function CountDisplayLen(ByVal aSize As Integer) As Integer
        If aSize >= 0 And aSize <= 3 Then
            Return aSize * 2
        End If
        If aSize >= 4 And aSize <= 7 Then
            Return aSize * 2 + 1
        End If
        If aSize >= 8 And aSize <= 11 Then
            Return aSize * 2 + 2
        End If
        If aSize >= 11 And aSize <= 15 Then
            Return aSize * 2 + 3
        End If
        Throw New Exception("Wrong CountDisplayLen value")
    End Function
    Private Sub ClearSelection()
        RTBStr.Selection.Select(_SelectStrStartP, _SelectStrEndP)
        RTBStr.Selection.ClearAllProperties()
        RTBHex.Selection.Select(_SelectStartP, _SelectEndP)
        RTBHex.Selection.ClearAllProperties()
    End Sub
    Private Sub SetStrSelection(ByVal aStart As Long, ByVal aEnd As Long, ByVal aTopRow As Double)
        If _Selected Then
            RTBStr.Selection.Select(_SelectStrStartP, _SelectStrEndP)
            RTBStr.Selection.ClearAllProperties()
        End If

        Dim iStartP As TextPointer

        iStartP = RTBStr.Document.ContentStart
        _SelectStrStartP = iStartP.GetPositionAtOffset(aStart)
        _SelectStrEndP = iStartP.GetPositionAtOffset(aEnd)
        RTBStr.Selection.Select(_SelectStrStartP, _SelectStrEndP)
        RTBStr.Selection.ApplyPropertyValue(TextElement.BackgroundProperty, Brushes.Green)

    End Sub
    Private Sub SetHexSelection(ByVal aStart As Long, ByVal aEnd As Long, ByVal aTopRow As Double)
        If _Selected Then
            RTBHex.Selection.Select(_SelectStartP, _SelectEndP)
            RTBHex.Selection.ClearAllProperties()
        End If

        Dim iStartP As TextPointer

        iStartP = RTBHex.Document.ContentStart
        _SelectStartP = iStartP.GetPositionAtOffset(aStart)
        _SelectEndP = iStartP.GetPositionAtOffset(aEnd)
        RTBHex.Selection.Select(_SelectStartP, _SelectEndP)
        RTBHex.Selection.ApplyPropertyValue(TextElement.BackgroundProperty, Brushes.Green)
        RTBHex.ScrollToVerticalOffset(aTopRow * _RowHeight)
        RTBOffset.ScrollToVerticalOffset(aTopRow * _RowHeight)
        RTBStr.ScrollToVerticalOffset(aTopRow * _RowHeight)
    End Sub

    Private Sub RTBStr_MouseWheel(ByVal sender As Object, ByVal e As System.Windows.Input.MouseWheelEventArgs) Handles RTBStr.MouseWheel
        SynHex(RTBStr.VerticalOffset)
    End Sub
    Private Sub SynHex(ByVal value As Double)


        RTBStr.ScrollToVerticalOffset(value)
        RTBHex.ScrollToVerticalOffset(value)
        RTBOffset.ScrollToVerticalOffset(value)
    End Sub

   
    Private Sub RTBHex_MouseWheel(ByVal sender As Object, ByVal e As System.Windows.Input.MouseWheelEventArgs) Handles RTBHex.MouseWheel
        SynHex(RTBHex.VerticalOffset)
    End Sub

    Private Sub RTBOffset_MouseWheel(ByVal sender As Object, ByVal e As System.Windows.Input.MouseWheelEventArgs) Handles RTBOffset.MouseWheel
        SynHex(RTBOffset.VerticalOffset)
    End Sub
  

   

    Private Sub RTBOffset_ScrollChanged(ByVal sender As System.Object, ByVal e As System.Windows.Controls.ScrollChangedEventArgs)
        SynHex(RTBOffset.VerticalOffset)
    End Sub

    Private Sub RTBHex_ScrollChanged(ByVal sender As System.Object, ByVal e As System.Windows.Controls.ScrollChangedEventArgs)
        SynHex(RTBHex.VerticalOffset)
    End Sub

    Private Sub RTBStr_ScrollChanged(ByVal sender As System.Object, ByVal e As System.Windows.Controls.ScrollChangedEventArgs)
        SynHex(RTBStr.VerticalOffset)
    End Sub
End Class
